package com.recsmile.sgs.util;

import com.recsmile.sgs.Cmd;
import com.recsmile.sgs.core.Command;
import com.recsmile.sgs.core.Packet;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class CommandManager {

    private CommandManager(){}

    private static Map<Short, Class> caches = new HashMap<Short, Class>();

    private static Map<String, Short> cachesByName = new HashMap<String, Short>();

    private static Map<String, Class> packet2commonds = new HashMap<>();

    public static void register(Set<Class<?>> clses){
        for (Class<?> cls : clses){
            if(cls.isAnnotationPresent(Cmd.class) && Packet.class.isAssignableFrom(cls)){
                caches.put(cls.getAnnotation(Cmd.class).value(), cls);
                cachesByName.put(cls.getName(), cls.getAnnotation(Cmd.class).value());
            }

        }
    }

    public static Class find(short code){
        return caches.get(code);
    }


    public static Short findByClsName(String name){
        return cachesByName.get(name);
    }

    public static void load(){
        Set<Class<?>> classSet = ClassUtil.getClasses("com.recsmile.sgs");
        register(classSet);
        for (Class cls: classSet) {
            if(Command.class.isAssignableFrom(cls) && cls.isInterface()){
                Type genericSuperclass = cls.getGenericSuperclass();
                if(genericSuperclass != null && ParameterizedType.class.isAssignableFrom(genericSuperclass.getClass())){
                    Class type = (Class) ((ParameterizedType)genericSuperclass).getActualTypeArguments()[0];
                    packet2commonds.put(type.getName(), cls);
                    System.out.println(type.getName()+","+cls.getName());
                }
            }

        }
    }


    public static <T extends Command>  T newInstance(String packetClsName){
        try {
            return (T)packet2commonds.get(packetClsName).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

}